﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Gakita.Model
{
    /* This class handles the logic for the player object */
    class Player
    {
        private Vector2 _standardStartPosition                                  =       new Vector2(1.0f, 17.9f);
        private Vector2 _startPositionAtLevelFour                               =       new Vector2(4.2f, 18.9f);

        private Vector2 _centerBottomPosition;
        private Vector2 _startPosition;
        private int _livesLeft                                                  =       3;
        private Vector2 _speed                                                  =       new Vector2(0f, 0);
        private int _timesJumped                                                =       0;
        private bool _isPlayerStandingOnFlyingPlatform                          =       false;
        private Miscellaneous.FlyingPlatform _platformCurrentlyStandingOn       =       null;

        public Vector2 _size                                                  =       new Vector2(0.85f, 0.60f);

        public Player()
        {
            _startPosition = _standardStartPosition;
            _centerBottomPosition = _startPosition;
        }

        public void Update(float aElapsedTime)
        {
            Vector2 gravityAcceleration = new Vector2(0.0f, 12f);

            _centerBottomPosition = _centerBottomPosition + _speed * aElapsedTime + gravityAcceleration * aElapsedTime * aElapsedTime;
            
            // If the player is standing on a flying platform, we first check if he's walked off the platform and is below it, 
            // in which case we unassign the platform from the player. If the player is still standing on the platform,
            // we add the platforms speed to the players position, so that the player moves with the platform. 
            if (_isPlayerStandingOnFlyingPlatform == true)
            {
                if (IsPlayerBelowPlatform())
                {
                    RemovePlatform();
                }
                else
                {
                    _centerBottomPosition += _platformCurrentlyStandingOn.getPlatformSpeed() * aElapsedTime;
                }
            }

            _speed = _speed + aElapsedTime * gravityAcceleration;

            _speed.X = _speed.X/2;

            // We don't allow the player to move outside of the screen to the left or right, so if he tries that, we moves him back.
            if (_centerBottomPosition.X - _size.X / 2 < 0)
            {
                _centerBottomPosition.X = _size.X / 2;
            }
            else if (_centerBottomPosition.X + _size.X / 2 > Level._levelWidth)
            {
                _centerBottomPosition.X = Level._levelWidth - _size.X / 2;
            }

        }

        /* This method checks if the player has walked off his current platform. */
        private bool IsPlayerBelowPlatform()
        {
            if (_centerBottomPosition.Y > _platformCurrentlyStandingOn.GetPosition().Y + 0.1)
            {
                return true;
            }
            return false;
        }

        /* This method makes the player jump */
        public void DoJump()
        {
            /* Unassign the player from his current platform, since he can no longer be standing on it, if he jumped */
            if (_isPlayerStandingOnFlyingPlatform == true)
            {
                RemovePlatform();
            }
            _speed.Y = -6.6f;
            _timesJumped++;
        }

        public void ResetTimesJumped()
        {
            _timesJumped = 0;
        }

        public void ReturnPlayerToStartPosition()
        {
            _centerBottomPosition = _startPosition;
        }

        public void SetPlayerStartingPositionToStandard()
        {
            _startPosition = _standardStartPosition;
        }

        public void ChangePlayerStartingPositionToLevelFour()
        {
            _startPosition = _startPositionAtLevelFour;
        }

        /* This method gives the player a small speed upwards, to make him bounce. Is called when the player kills a rabbit */
        public void Bounce()
        {
            _speed.Y = -6f;
        }

        /* This method resets the player position and speed. The player also loses a life */
        public void Die()
        {
            ResetPlayerPosition();
            _livesLeft -= 1;
        }

        /* This method restores the player to his original position and speed */
        public void ResetPlayerPosition()
        {
            ReturnPlayerToStartPosition();
            RemovePlatform();
            _speed = Vector2.Zero;
        }

        public void MoveLeft()
        {
            _speed.X = -4;
        }

        public void MoveRight()
        {
            _speed.X = 4;
        }

        /* This method assigns a platform to a player. The platform is used in the update method to allow 
           the player to move with the platform while standing on it */
        public void SetPlatform(Miscellaneous.FlyingPlatform aPlatform)
        {
            if (_isPlayerStandingOnFlyingPlatform == false)
            {
                _platformCurrentlyStandingOn = aPlatform;
                _isPlayerStandingOnFlyingPlatform = true;
            }
        }

        public void RemovePlatform()
        {
            _isPlayerStandingOnFlyingPlatform = false;
            _platformCurrentlyStandingOn = null;
        }

        public void SetSpeed(float aXPosition, float aYPosition)
        {
            _speed.X = aXPosition;
            _speed.Y = aYPosition;
        }

        public int GetLivesLeft()
        {
            return _livesLeft;
        }

        public void SetLivesLeft(int aLivesLeft)
        {
            _livesLeft = aLivesLeft;
        }

        public Vector2 GetSpeed()
        {
            return _speed;
        }

        public Vector2 GetPosition()
        {
            return _centerBottomPosition;
        }

        public void SetPosition(float aXPosition, float aYPosition)
        {
            _centerBottomPosition.X = aXPosition;
            _centerBottomPosition.Y = aYPosition;
        }

        public int GetNumberOfJumps()
        {
            return _timesJumped;
        }
    }
}
